package com.zy.experience_system.aop;

import com.zy.experience_system.util.HttpRequestUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Aspect  // 声明这是一个aop类
@Component // 被spring 所管理
@Slf4j
public class ControllerAspect {
    private static final int slowReq = 5000;// 超过这个时间的，接口访问过慢
    private Object runAndSaveLog(ProceedingJoinPoint pjp) throws Throwable{
        long beginTime = System.currentTimeMillis();

        //  获取当前请求对象
        String userId = "无";
        String perms = "无";
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        HttpServletRequest request = attributes.getRequest();
        Object object = request.getAttribute("user_claims");
        if (object != null) {
            Claims claims = (Claims) object;
            userId = claims.getId();
            perms = (String) claims.get("perms");
        }
//        String host = request.getHeader("Host");
        String host = HttpRequestUtil.getIpAddress(request);
        if (HttpRequestUtil.validate(host)==false){
            host = "无法获取";
        }

        Object result = null;
        Object target = pjp.getTarget();
        Signature signature = pjp.getSignature();

        try {
            result = pjp.proceed();
        }catch (Throwable e){
            log.error("------------------------------------------");
            log.error("Controller : " + target.getClass().getSimpleName());
            log.error("方法 : " + signature.getName());
            log.error("错误原因 : " + e.getMessage());
            //  记录谁访问了这个接口，已登录用户
            log.error("调用者用户名 : " + userId );
            log.error("调用者权限 : " + perms );
            log.error( "调用者IP : " + host);
            throw e;
        }finally {

        }

        long endTime = System.currentTimeMillis();
        log.info("------------------------------------------");
        log.info("Controller : " + target.getClass().getSimpleName());
        log.info("方法 : " + signature.getName());
        log.info("本方法用时 : " + (endTime - beginTime));
        //  记录谁访问了这个接口，已登录用户
        log.info("调用者用户名 : " + userId );
        log.info("调用者权限 : " + perms );
        log.info( "调用者IP : " + host);
        //  还可以判断接口时间，统计slowRequest
        if (endTime - beginTime>slowReq){
            long outTime = endTime - beginTime - slowReq;
            log.warn("------------------------------------------");
            log.warn("Controller : " + target.getClass().getSimpleName());
            log.warn("方法 : " + signature.getName());
            log.warn( "接口调用过慢，已超时 : " + outTime + "毫秒");
        }
        return result;
    }


    @Around("@within(org.springframework.stereotype.Controller)")
    Object aroundController(ProceedingJoinPoint pjp) throws Throwable {
        return runAndSaveLog(pjp);
    }

    @Around("execution(* com.zy.experience_system.interceptor.JwtInterceptor.preHandle())")
    Object aroundJwtInterceptor(ProceedingJoinPoint pjp) throws Throwable {
        return runAndSaveLog(pjp);
    }

    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    Object aroundRestController(ProceedingJoinPoint pjp) throws Throwable {
        return runAndSaveLog(pjp);
    }
}
